#pragma once

enum class FieldType : uint8_t { INT = 1, STRING = 2,DATETIME = 3 };
enum class CompareOp { EQ,NOT_EQ,LESS,LESS_EQUAL,GREATER,GREATER_EQUAL };
enum class SqlKind { Create, Insert, Update, Select, Delete, Unknown };
enum class PageType : uint32_t { DATA = 1, INDEX = 2 };
enum class TrxStatus { ACTIVE ,COMMIT, ROLLBACK };
// 锁SHARED 共享锁 只读，防止写
// 锁EXCLUSIVE 锁写入 只允许一个事务“写”数据，其他事务不能读也不能写。
// 锁TABLE 表锁,不许读也不许写
enum class LockType { SHARED, EXCLUSIVE,TABLE };
enum class LockStatus { WAITING, GRANTED };
/* 隔离级别:READ UNCOMMITTED（读未提交）
可以读到别人未提交的数据（脏读）
实现：直接读最新版本，不用 MVCC，不加读锁
READ COMMITTED（读已提交）
只能读到别人已提交的数据
每条 SELECT 生成新的 ReadView
实现：用 MVCC，每语句创建快照
REPEATABLE READ（可重复读）
事务内多次读同一行，结果一致
事务内第一次 SELECT 生成 ReadView，后续复用
实现：用 MVCC，事务级别的快照
SERIALIZABLE（串行化）
最严格，避免幻读
SELECT 也会加共享锁
实现：所有读写都加锁*/
enum class IsolationLevel {READ_UNCOMMITTED,READ_COMMITTED,REPEATABLE_READ,SERIALIZABLE};
struct DataConfig {
    std::string tableName;
    std::string tablePath;
    uint32_t schemaSize;
};

struct SystemConfig{
    std::string dataPath;
    std::string undoLogPath;
    std::string binLogPath;
    std::string redoLogPath;
    std::vector<DataConfig> dataConfigs;
};

struct FileHeader{
    uint32_t lastPage = 0;
    uint32_t pageCount= 2;
    uint32_t schemaCount = 0;
    uint32_t maxRecordNo = 0;
    uint32_t rootIndexPageNo = 0;
};

struct PageHead{
    // 当前page 编号
    uint32_t pageNo;
    // type
    PageType pageType;
    // 下一个page 编号
    uint32_t pageNext;
    // 上一个page编号
    uint32_t pagePrev;
    // 数据一共多少条
    uint32_t recordCount;
    //最大事务id
    uint32_t maxTrxId;
    //第一条数据偏移量
    uint32_t firstRecord;
    //最后一条数据偏移量
    uint32_t lastRecord;
    //空闲区偏移量
    uint32_t freeOffset;
    // 空闲区大小
    uint32_t freeSize;
    //页目录大小
    uint32_t slotSize;
    //最大主键id
    uint32_t maxRecordNo;
};


struct FieldInfo {
    char name[64];     // 固定64字节
    FieldType type;
    bool isPrimary = false;
    bool autoIncrement = false;
};

struct Cell {
    bool is_null=true;
    FieldType type = FieldType::INT;
    uint64_t i64 =0;
    std::string str;  // 指向实际字节
    uint8_t datetime[5];
};

struct IndexRecord {
    uint32_t deleteType = 0;
    uint32_t heapNo = 0;
    uint32_t nextRecord = 0;
    // 指向的下一个节点编号
    uint32_t childPageNo=0;
    //主键
    uint32_t key = 0;
};



/*
 * 功能区
 * */

// 比较
struct SqlFilter {
    CompareOp type = CompareOp::EQ;
    size_t colIndex;
    Cell value;
};
// set赋值
struct UpdateSetItem {
    size_t colIndex;
    Cell value;
};

struct UpdatePlan {
    std::string table;
    std::vector<UpdateSetItem> sets;
    std::vector<SqlFilter> where;
};

struct DeletePlan {
    std::string table;
    std::vector<SqlFilter> where;
};





struct IdbParam {
    std::fstream *file = nullptr;
    FileHeader *fileHeader = nullptr;
    PageHead * pageHead = nullptr;
    std::vector<FieldInfo> *fieldList = nullptr;
    std::vector<uint8_t> *page = nullptr;
};


struct IbdConfig {
    std::string name;
    std::unique_ptr<std::fstream> file;
    FileHeader fileHeader;
    std::vector<FieldInfo> fieldInfo;
//    std::unique_ptr<std::fstream> file;
//    std::unique_ptr<FileHeader> fileHeader;
//    std::unique_ptr<FieldInfo> fieldInfo;
};



// std::lock_guard<std::mutex> guard(mtx); 互斥锁
struct LockRecord {
    std::string tableName;
    uint32_t pageNo;     // 页号
    uint32_t heapNo;     // 页内记录号
    LockType type;
    uint64_t trxId;
    LockStatus status;
};
struct UndoRecord {
    uint64_t undoLSN;        // 这条undo记录的LSN
    uint64_t trxId;          // 所属事务ID
//    UndoType undoType;       // INSERT_UNDO/UPDATE_UNDO/DELETE_UNDO
    uint32_t tableId;        // 表ID
    uint32_t pageNo;         // 页号
    uint32_t heapNo;         // 记录号
    std::vector<Cell> oldValues;  // 旧值
    UndoRecord* prevUndo;    // 指向该事务的上一条undo记录
};


struct Transaction{
    uint64_t trxId;
    TrxStatus trxStatus;
    // 时间戳
    uint64_t startTime;       // 事务开始时间
    uint64_t commitTime;      // 提交时间

    IsolationLevel isolationLevel;
    std::vector<LockRecord*> lockList;  // 持有的锁列表

    // LSN = 偏移量，如果是循环日志，那么就要+ 大小乘以循环次数
    uint64_t undoLogStartLSN; // 该事务第一条undo记录的LSN
    std::vector<UndoRecord*> undoList; // undo记录链表头

    uint64_t firstLogLSN;     // 该事务第一条redo日志的LSN
    uint64_t lastLogLSN;      // 最后一条redo日志的LSN

    // Binlog 相关（如果开启）
    uint64_t binlogPos;       // 在binlog中的位置
    bool binlogWritten;       // 是否已写入binlog
};
struct ReadView {
    std::vector<Transaction> activeTrxIds;
    uint64_t minTrxId;
    uint64_t maxTrxId;
    uint64_t creatorTrxId;
};
struct Session {
    uint64_t sessionId{0};
    int socket{-1};
    std::string user;
    std::string database;
    bool autocommit{true};
    IsolationLevel isolation{IsolationLevel::READ_COMMITTED};
    std::unique_ptr<Transaction> currentTrx; // 有事务则非空
    std::chrono::steady_clock::time_point connectedTime;
};
struct Context {
    Transaction *trx;
    Session *session;
    std::string sql;
    SqlKind sqlKind;
    ReadView * readView;
    std::string tableName;
};

struct LockKey{
    uint32_t tableName;
    uint32_t pageNo;
    uint32_t heapNo;
    bool operator==(const LockKey& rhs) const noexcept {
        return tableName == rhs.tableName &&
               pageNo    == rhs.pageNo    &&
               heapNo    == rhs.heapNo;
    }
};
namespace std {
    template <>
    struct hash<LockKey> {
        std::size_t operator()(const LockKey& k) const {
            return ((std::hash<uint32_t>()(k.tableName) ^
                     (std::hash<uint32_t>()(k.pageNo) << 1)) >> 1) ^
                   (std::hash<uint32_t>()(k.heapNo) << 1);
        }
    };
}